﻿using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using CTS.Com.Domain.Exceptions;
using CTS.Com.Domain.Helper;
using CTS.Data.Domain.Helper;

namespace CTS.Data
{
    /// <summary>
    /// ContextBase
    /// </summary>
    public class ContextBase : DataContext
    {
        public ContextBase(string connection) : base(connection) { }
        public ContextBase(string connection, MappingSource mapping) : base(connection, mapping) { }
        public ContextBase(IDbConnection connection) : base(connection) { }
        public ContextBase(IDbConnection connection, MappingSource mapping) : base(connection, mapping) { }

        /// <summary>
        /// Thực thi query trực tiếp trên database.
        /// </summary>
        public IEnumerable<TResult> ExecuteQuery<TResult>(string sql, object param)
        {
            // Khai báo biến cục bộ
            var type = typeof(TResult);
            var lresult = DataHelper.CreateList<TResult>();
            // Tạo command
            var cmd = Connection.CreateCommand();
            // Gán sql vào command đã tạo
            cmd.CommandText = sql;
            // Lấy thuộc tính của đối tượng
            var lprop = DataHelper.GetProperties(param);
            // Khai báo biến dùng trong loop
            DbParameter pr;
            // Diệt thuộc tính của đối tượng            
            foreach (var prop in lprop) {
                pr = cmd.CreateParameter();
                pr.ParameterName = "@" + prop.Key;
                pr.Value = DaoHelper.ToSqlData(prop.Value);
                cmd.Parameters.Add(pr);
            }
            // Mở kết nối đến database
            Connection.Open();
            // Tiến hành đọc dữ liệu
            var reader = cmd.ExecuteReader();
            // Khai báo biến dùng trong loop
            TResult rs; string nm; object vl;
            // Diệt các dữ liệu đã đọc
            while (reader.Read()) {
                if (DataCheckHelper.IsTypeSys(type)) {
                    rs = (TResult)reader.GetValue(0);
                } else if (type.IsClass && !(type.IsAbstract || type.IsInterface)) {
                    rs = DataHelper.CreateObject<TResult>();
                    for (int i = 0; i < reader.FieldCount; i++) {
                        nm = reader.GetName(i);
                        vl = reader.GetValue(i);
                        if (reader.IsDBNull(i)) {
                            vl = null;
                        }
                        DataHelper.SetProperty(rs, nm, vl);
                    }
                } else {
                    throw new ExecuteException("F_MSG_00003", type.FullName);
                }
                lresult.Add(rs);
            }
            // Đống kết nối đến database
            Connection.Close();
            // Kết quả trả về
            return lresult.AsEnumerable();
        }
    }
}